home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / umich / tex / texinfo.zoo / texindex.c < prev    next >
C/C++ Source or Header  |  1991-04-16  |  39KB  |  1,609 lines

  1. /* Prepare Tex index dribble output into an actual index.
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 1, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. #include <stdio.h>
  19. #include <ctype.h>
  20. #include <errno.h>
  21.  
  22. #ifdef VMS
  23. #ifndef VAX11C
  24. #define noshare
  25. #endif
  26.  
  27. #include <perror.h>
  28. #include <file.h>
  29.  
  30. #define EXIT_SUCCESS ((1 << 28) | 1)
  31. #define EXIT_FATAL ((1 << 28) | 4)
  32. #define unlink delete
  33. #define tell(fd) lseek(fd, 0L, 1)
  34.  
  35. #else /* Not VMS */
  36.  
  37. #ifdef USG
  38. #include <sys/types.h>
  39. #include <sys/fcntl.h>
  40. #endif
  41. #include <sys/file.h>
  42.  
  43. #define EXIT_SUCCESS 0
  44. #define EXIT_FATAL 1
  45.  
  46. #endif /* Not VMS */
  47.  
  48. #ifdef atarist
  49. long _stksize = -1L;
  50. #endif
  51.  
  52. #ifndef L_XTND
  53. #define L_XTND 2
  54. #endif
  55.  
  56. #ifdef VMS
  57. extern noshare int sys_nerr;
  58. extern noshare char *sys_errlist[];
  59. #else
  60. extern int sys_nerr;
  61. extern char *sys_errlist[];
  62. #endif
  63.  
  64. /* When sorting in core, this structure describes one line
  65.  and the position and length of its first keyfield.  */
  66.  
  67. struct lineinfo
  68.   {
  69.     char *text;        /* The actual text of the line */
  70.     union
  71.       {            /* The start of the key (for textual comparison) */
  72.     char *text;
  73.     long number;    /* or the numeric value (for numeric comparison) */
  74.       } key;
  75.     long keylen;    /* Length of key field */
  76.   };
  77.  
  78. /* This structure describes a field to use as a sort key */
  79.  
  80. struct keyfield
  81.   {
  82.     int startwords;        /* # words to skip  */
  83.     int startchars;        /*  and # additional chars to skip, to start of field */
  84.     int endwords;        /* similar, from beg (or end) of line, to find end of field */
  85.     int endchars;
  86.     char ignore_blanks;        /* Ignore spaces and tabs within the field */
  87.     char fold_case;        /* Convert upper case to lower before comparing */
  88.     char reverse;        /* Compare in reverse order */
  89.     char numeric;        /* Parse text as an integer and compare the integers */
  90.     char positional;        /* Sort according to position within the file */
  91.     char braced;        /* Count balanced-braced groupings as fields */
  92.   };
  93.  
  94. /* Vector of keyfields to use */
  95.  
  96. struct keyfield keyfields[3];
  97.  
  98. /* Number of keyfields stored in that vector.  */
  99.  
  100. int num_keyfields = 3;
  101.  
  102. /* Vector of input file names, terminated with a zero (null pointer) */
  103.  
  104. char **infiles;
  105.  
  106. /* Vector of corresponding output file names, or zero meaning default it */
  107.  
  108. char **outfiles;
  109.  
  110. /* Length of `infiles' */
  111.  
  112. int num_infiles;
  113.  
  114. /* Pointer to the array of pointers to lines being sorted */
  115.  
  116. char **linearray;
  117.  
  118. /* The allocated length of `linearray'. */
  119.  
  120. long nlines;
  121.  
  122. /* Directory to use for temporary files.  On Unix, it ends with a slash.  */
  123.  
  124. char *tempdir;
  125.  
  126. /* Start of filename to use for temporary files.  */
  127.  
  128. char *tempbase;
  129.  
  130. /* Number of last temporary file.  */
  131.  
  132. int tempcount;
  133.  
  134. /* Number of last temporary file already deleted.
  135.  Temporary files are deleted by `flush_tempfiles' in order of creation.  */
  136.  
  137. int last_deleted_tempcount;
  138.  
  139. /* During in-core sort, this points to the base of the data block
  140.  which contains all the lines of data.  */
  141.  
  142. char *text_base;
  143.  
  144. /* Additional command switches */
  145.  
  146. int keep_tempfiles;    /* Nonzero means do not delete tempfiles -- for debugging */
  147.  
  148. /* Forward declarations of functions in this file */
  149.  
  150. void decode_command ();
  151. void sort_in_core ();
  152. void sort_offline ();
  153. char **parsefile ();
  154. char *find_field ();
  155. char *find_pos ();
  156. long find_value ();
  157. char *find_braced_pos ();
  158. char *find_braced_end ();
  159. void writelines ();
  160. int compare_full ();
  161. long readline ();
  162. int merge_files ();
  163. int merge_direct ();
  164. char *concat ();
  165. char *maketempname ();
  166. void flush_tempfiles ();
  167. char *tempcopy ();
  168.  
  169. extern char *mktemp ();
  170.  
  171. #define MAX_IN_CORE_SORT 500000
  172.  
  173. int
  174. main (argc, argv)
  175.      int argc;
  176.      char **argv;
  177. {
  178.   int i;
  179.  
  180.   tempcount = 0;
  181.   last_deleted_tempcount = 0;
  182.  
  183.   /* Describe the kind of sorting to do. */
  184.   /* The first keyfield uses the first braced field and folds case */
  185.   keyfields[0].braced = 1;
  186.   keyfields[0].fold_case = 1;
  187.   keyfields[0].endwords = -1;
  188.   keyfields[0].endchars = -1;
  189.   /* The second keyfield uses the second braced field, numerically */
  190.   keyfields[1].braced = 1;
  191.   keyfields[1].numeric = 1;
  192.   keyfields[1].startwords = 1;
  193.   keyfields[1].endwords = -1;
  194.   keyfields[1].endchars = -1;
  195.   /* The third keyfield (which is ignored while discarding duplicates)
  196.      compares the whole line */
  197.   keyfields[2].endwords = -1;
  198.   keyfields[2].endchars = -1;
  199.  
  200.   decode_command (argc, argv);
  201.  
  202.   tempbase = mktemp (concat ("txiXXXXXX", "", ""));
  203.  
  204.   /* Process input files completely, one by one.  */
  205.  
  206.   for (i = 0; i < num_infiles; i++)
  207.     {
  208.       int desc;
  209.       long ptr;
  210.       char *outfile;
  211.       char *p;
  212.  
  213.       desc = open (infiles[i], 0, 0);
  214.       if (desc < 0) pfatal_with_name (infiles[i]);
  215.       lseek (desc, 0, L_XTND);
  216.       ptr = tell (desc);
  217.       close (desc);
  218.  
  219.       outfile = outfiles[i];
  220.       if (!outfile)
  221.     {
  222.       outfile = concat (infiles[i], "s", "");
  223.     }
  224.  
  225.       if (ptr < MAX_IN_CORE_SORT)
  226.         /* Sort a small amount of data */
  227.         sort_in_core (infiles[i], ptr, outfile);
  228.       else
  229.         sort_offline (infiles[i], ptr, outfile);
  230.     }
  231.  
  232.   flush_tempfiles (tempcount);
  233.   exit (EXIT_SUCCESS);
  234. }
  235.  
  236. /* This page decodes the command line arguments to set the parameter variables
  237.  and set up the vector of keyfields and the vector of input files */
  238.  
  239. void
  240. decode_command (argc, argv)
  241.      int argc;
  242.      char **argv;
  243. {
  244.   int i;
  245.   char **ip;
  246.   char **op;
  247.  
  248.   /* Store default values into parameter variables */
  249.  
  250. #ifdef VMS
  251.   tempdir = "sys$scratch:";
  252. #else
  253.   tempdir = "/tmp/";
  254. #endif
  255.  
  256.   keep_tempfiles = 0;
  257.  
  258.   /* Allocate argc input files, which must be enough.  */
  259.  
  260.   infiles = (char **) xmalloc (argc * sizeof (char *));
  261.   outfiles = (char **) xmalloc (argc * sizeof (char *));
  262.   ip = infiles;
  263.   op = outfiles;
  264.  
  265.   /* First find all switches that control the default kind-of-sort */
  266.  
  267.   for (i = 1; i < argc; i++)
  268.     {
  269.       int tem = classify_arg (argv[i]);
  270.       char c;
  271.       char *p;
  272.  
  273.       if (tem <= 0)
  274.     {
  275.       *ip++ = argv[i];
  276.       *op++ = 0;
  277.       continue;
  278.     }
  279.       if (tem > 1)
  280.     {
  281.       if (i + 1 == argc)
  282.         fatal ("switch %s given with no argument following it", argv[i]);
  283.       else if (!strcmp (argv[i], "-T"))
  284.         tempdir = argv[i + 1];
  285.       else if (!strcmp (argv[i], "-o"))
  286.         *(op - 1) = argv[i + 1];
  287.       i += tem - 1;
  288.       continue;
  289.     }
  290.  
  291.       p = &argv[i][1];
  292.       while (c = *p++)
  293.     switch (c)
  294.       {
  295.       case 'k':
  296.         keep_tempfiles = 1;
  297.         break;
  298.  
  299.       default:
  300.         fatal ("invalid command switch %c", c);
  301.       }
  302.     switchdone: ;
  303.     }
  304.  
  305.   /* Record number of keyfields, terminate list of filenames */
  306.  
  307.   num_infiles = ip - infiles;
  308.   *ip = 0;
  309. }
  310.  
  311. /* Return 0 for an argument that is not a switch;
  312.  for a switch, return 1 plus the number of following arguments that the switch swallows.
  313. */
  314.  
  315. int
  316. classify_arg (arg)
  317.      char *arg;
  318. {
  319.   if (!strcmp (arg, "-T") || !strcmp (arg, "-o"))
  320.     return 2;
  321.   if (arg[0] == '-')
  322.     return 1;
  323.   return 0;
  324. }
  325.  
  326. /* Create a name for a temporary file */
  327.  
  328. char *
  329. maketempname (count)
  330.      int count;
  331. {
  332.   char tempsuffix[10];
  333.   sprintf (tempsuffix, "%d", count);
  334.   return concat (tempdir, tempbase, tempsuffix);
  335. }
  336.  
  337. /* Delete all temporary files up to the specified count */
  338.  
  339. void
  340. flush_tempfiles (to_count)
  341.      int to_count;
  342. {
  343.   if (keep_tempfiles) return;
  344.   while (last_deleted_tempcount < to_count)
  345.     unlink (maketempname (++last_deleted_tempcount));
  346. }
  347.  
  348. /* Copy an input file into a temporary file, and return the temporary file name */
  349.  
  350. #define BUFSIZE 1024
  351.  
  352. char *
  353. tempcopy (idesc)
  354.      int idesc;
  355. {
  356.   char *outfile = maketempname (++tempcount);
  357.   int odesc;
  358.   char buffer[BUFSIZE];
  359.  
  360.   odesc = open (outfile, O_WRONLY | O_CREAT, 0666);
  361.  
  362.   if (odes